<template>
  <div class="text-editor-container">
    <div
      ref="editableDiv"
      class="editable-div"
      contenteditable="true"
      @input="handleInput"
      @mouseup="handleSelection"
      @keyup="handleSelection"
      @paste="handlePaste"
    ></div>

    <div class="toolbar">
      <button @click="undo" :disabled="!canUndo">↺ 撤销 (Ctrl+Z)</button>
      <button @click="redo" :disabled="!canRedo">↻ 重做 (Ctrl+Y)</button>

      <select v-model="selectedTag" class="tag-select">
        <option value="span">span</option>
        <option value="div">div</option>
        <option value="strong">strong</option>
        <option value="em">em</option>
        <option value="mark">mark</option>
        <option value="code">code</option>
      </select>

      <select v-model="selectedClass" class="class-select">
        <option value="">无样式</option>
        <option value="highlight">高亮</option>
        <option value="bold">加粗</option>
        <option value="color-red">红色</option>
        <option value="underline">下划线</option>
        <option value="custom">自定义</option>
      </select>

      <input
        v-if="selectedClass === 'custom'"
        v-model="customClass"
        placeholder="输入自定义class"
        class="custom-class-input"
      />

      <button @click="wrapSelection" :disabled="!hasSelection">应用标签 (Ctrl+Q)</button>

      <button @click="getHTMLContent">获取HTML内容</button>
      <button @click="clearContent">清空内容</button>
    </div>

    <div v-if="htmlContent" class="output">
      <h4>生成的HTML:</h4>
      <pre>{{ htmlContent }}</pre>
    </div>
  </div>
</template>

<script>
export default {
  name: "EnhancedTextEditor",
  data() {
    return {
      hasSelection: false,
      htmlContent: "",
      lastSelection: null,
      history: [],
      historyIndex: -1,
      selectedTag: "span",
      selectedClass: "highlight",
      customClass: "",
      ignoreNextInput: false,
    };
  },
  computed: {
    canUndo() {
      return this.historyIndex > 0;
    },
    canRedo() {
      return this.historyIndex < this.history.length - 1;
    },
    currentClassName() {
      return this.selectedClass === "custom" ? this.customClass : this.selectedClass;
    },
  },
  methods: {
    handleInput(event) {
      if (this.ignoreNextInput) {
        this.ignoreNextInput = false;
        return;
      }
      this.saveToHistory();
    },

    handleSelection() {
      const selection = window.getSelection();
      this.hasSelection = !selection.isCollapsed && selection.rangeCount > 0;

      if (this.hasSelection) {
        this.lastSelection = selection.getRangeAt(0);
      }
    },

    wrapSelection() {
      if (!this.hasSelection && !this.lastSelection) return;

      const range = this.lastSelection || window.getSelection().getRangeAt(0);
      const selectedContent = range.cloneContents();

      // 检查选中的内容是否已经在相同标签和类中
      let alreadyWrapped = false;
      if (selectedContent.childNodes.length === 1) {
        const node = selectedContent.firstChild;
        if (node.nodeName === this.selectedTag.toUpperCase()) {
          const classMatch = this.currentClassName
            ? node.classList.contains(this.currentClassName)
            : node.classList.length === 0;

          if (classMatch) {
            // 取消包裹
            const contents = document.createDocumentFragment();
            while (node.firstChild) {
              contents.appendChild(node.firstChild);
            }
            range.deleteContents();
            range.insertNode(contents);
            alreadyWrapped = true;
          }
        }
      }

      if (!alreadyWrapped) {
        // 创建新元素
        const element = document.createElement(this.selectedTag);
        if (this.currentClassName) {
          element.className = this.currentClassName;
        }

        // 包裹选中的内容
        element.appendChild(range.extractContents());
        range.insertNode(element);
      }

      // 保存到历史记录
      this.saveToHistory();

      // 清除选区并更新状态
      window.getSelection().removeAllRanges();
      this.hasSelection = false;
      this.$refs.editableDiv.focus();
    },

    saveToHistory() {
      const content = this.$refs.editableDiv.innerHTML;

      // 如果内容没有变化，则不保存
      if (this.history[this.historyIndex] === content) return;

      // 截断当前索引之后的历史
      this.history = this.history.slice(0, this.historyIndex + 1);

      // 添加到历史记录
      this.history.push(content);
      this.historyIndex = this.history.length - 1;

      // 限制历史记录数量
      if (this.history.length > 50) {
        this.history.shift();
        this.historyIndex--;
      }
    },

    undo() {
      if (this.canUndo) {
        this.historyIndex--;
        this.applyHistoryState();
      }
    },

    redo() {
      if (this.canRedo) {
        this.historyIndex++;
        this.applyHistoryState();
      }
    },

    applyHistoryState() {
      this.ignoreNextInput = true;
      this.$refs.editableDiv.innerHTML = this.history[this.historyIndex];
    },

    getHTMLContent() {
      this.htmlContent = this.$refs.editableDiv.innerHTML;
    },

    clearContent() {
      this.$refs.editableDiv.innerHTML = "";
      this.htmlContent = "";
      this.hasSelection = false;
      this.lastSelection = null;
      this.saveToHistory();
    },

    handlePaste(event) {
      event.preventDefault();
      const text = (event.clipboardData || window.clipboardData).getData("text/plain");
      document.execCommand("insertText", false, text);
      this.saveToHistory();
    },
  },

  mounted() {
    // 初始化历史记录
    this.saveToHistory();

    // 添加键盘快捷键监听
    document.addEventListener("keydown", (e) => {
      if (e.ctrlKey || e.metaKey) {
        switch (e.key) {
          case "z":
            if (!e.shiftKey) {
              e.preventDefault();
              this.undo();
            }
            break;
          case "y":
            e.preventDefault();
            this.redo();
            break;
          case "Z":
            if (e.shiftKey) {
              e.preventDefault();
              this.redo();
            }
            break;
          case "q":
          case "Q":
            e.preventDefault();
            this.wrapSelection();
            break;
        }
      }
    });
  },
};
</script>

<style scoped>
.text-editor-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.editable-div {
  min-height: 150px;
  border: 1px solid #ccc;
  padding: 10px;
  margin-bottom: 10px;
  outline: none;
  white-space: pre-wrap;
}

.editable-div:focus {
  border-color: #409eff;
}

.toolbar {
  margin-bottom: 15px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.toolbar button {
  padding: 5px 10px;
  background: #f0f0f0;
  border: 1px solid #ddd;
  border-radius: 3px;
  cursor: pointer;
}

.toolbar button:hover {
  background: #e0e0e0;
}

.toolbar button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.tag-select,
.class-select {
  padding: 5px;
  border: 1px solid #ddd;
  border-radius: 3px;
}

.custom-class-input {
  padding: 5px;
  border: 1px solid #ddd;
  border-radius: 3px;
  width: 120px;
}

.output {
  margin-top: 20px;
  padding: 10px;
  background: #f5f5f5;
  border: 1px solid #ddd;
  border-radius: 3px;
}

/* 样式类定义 */
:deep(.highlight) {
  background-color: yellow;
}

:deep(.bold) {
  font-weight: bold;
}

:deep(.color-red) {
  color: red;
}

:deep(.underline) {
  text-decoration: underline;
}
</style>
